package com.cyd.product_service.cluster.consul;

import java.util.ArrayList;
import java.util.List;

import com.cyd.product_service.cluster.ClusterService;
import com.cyd.product_service.cluster.LoadBalance;
import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.QueryParams;
import com.ecwid.consul.v1.health.model.HealthService;
import com.ecwid.consul.v1.kv.model.GetValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * ConsulServiceSelector
 * Created by fangzhihong on 2017/11/25.
 */
public class ConsulServiceSelector extends AbstractConsulService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ConsulServiceSelector.class);

    private LoadBalance loadBalance;

    public ConsulServiceSelector(LoadBalance loadBalance) {
        this(new ConsulClient(), loadBalance);
    }

    public ConsulServiceSelector(ConsulClient consulClient, LoadBalance loadBalance) {
        super(consulClient);
        this.loadBalance = loadBalance;
    }

    public ConsulServiceSelector get() {
        return this;
    }

    public ClusterService select(String name) {
        List<ClusterService> serviceList = new ArrayList();
        for (HealthService service : consulClient.getHealthServices(
            name, true, QueryParams.DEFAULT).getValue()) {
            serviceList.add(getClusterService(service));
        }
        if (serviceList.size() == 0) {
            return null;
        }
        return loadBalance.select(serviceList);
    }

    public ClusterService selectMaster(String name) {
        String masterKey = name + MASTER_KEY_SUFFIX;
        GetValue masterValue = consulClient.getKVValue(masterKey).getValue();
        if (masterValue == null) {
            return null;
        }
        String masterServiceId = masterValue.getDecodedValue();
        LOGGER.info("Get master service id: " + masterServiceId);

        List<ClusterService> serviceList = new ArrayList();
        for (HealthService service : consulClient.getHealthServices( name, true, QueryParams.DEFAULT).getValue()) {
            ClusterService clusterService = getClusterService(service);
            if (clusterService.getId().equals(masterServiceId)) {
                LOGGER.info("Found master service, return service: " + clusterService.getId());
                return clusterService;
            }
            serviceList.add(clusterService);
        }

        // 原master服务不在健康服务列表里，重新选出
        LOGGER.info("Master service doesn't exist, reelect master service.");
        ClusterService newMasterService = loadBalance.select(serviceList);
        consulClient.setKVValue(masterKey, newMasterService.getId());
        return newMasterService;
    }

    private static ClusterService getClusterService(HealthService service) {
        ClusterService cs = new ClusterService();
        cs.setAddress(service.getService().getAddress());
        cs.setPort(service.getService().getPort());
        cs.setId(service.getService().getId());
        cs.setName(service.getService().getService());
        for (String tag : service.getService().getTags()) {
            if ("HTTP".equals(tag)) {
                cs.setServiceType(ClusterService.ServiceType.HTTP);
            } else if ("TCP".equals(tag)) {
                cs.setServiceType(ClusterService.ServiceType.TCP);
            } else if (tag.startsWith("weight:")) {
                cs.setWeight(Integer.parseInt(tag.substring(7)));
            }
        }
        return cs;
    }
}
